﻿using Blm.Utils.Utility;
using Blm.VisionCloud.FrameWork.Email;
using Blm.VisionCloud.FrameWork.VerifyCode;
using Language.Resource;
using Microsoft.Extensions.Localization;
using MimeKit;
using MimeKit.Text;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using VisionCloud.Domain.Common;
using VisionCloud.Domain.Repository.Interface.Sys;
using VisionCloud.Domain.UnitOfWork;
using VisionCloud.Utility;

namespace VisionCloud.Service.Sys
{
    /// <summary>
    /// 跨平台邮件服务
    /// </summary>
    public class CrossEmailService
    {
        private readonly IVerifyCode verifyCode;
        private readonly EMailHelper eMailHelper;

        public IUnitOfWork UnitOfWork { get; set; }
        public IStringLocalizer<ServiceResource> Localizer { set; get; }

        public ISysUserRepository SysUserRepository { get; set; }

        public CrossEmailService(IVerifyCode verifyCode, EMailHelper eMailHelper)
        {
            this.verifyCode = verifyCode;
            this.eMailHelper = eMailHelper;
        }

        public async Task<ApiResult> ResetPassWord(Domain.DtoModel.Sys.RegisterDto registerDto)
        {
            var resp = verifyCode.CheckCode(registerDto.Email, registerDto.VerifyCode);
            if (resp == 0)
            {
                return ApiResult.SetCode(AjaxCode.Fail, Localizer["YB0210"].Value);
            }
            if (resp == -1)
            {
                return ApiResult.SetCode(AjaxCode.Fail, Localizer["YB0211"].Value);
            }
            var entity = SysUserRepository.Update(t => t.Email.ToLower() == registerDto.Email.ToLower(), d => d.Password = registerDto.Password.GetMD5());
            var count = await UnitOfWork.SaveChangesAsync();
            return ApiResult.Success(Localizer["YB0212"].Value).SetData(entity);
        }

        /// <summary>
        /// 发送邮件
        /// </summary>
        /// <param name="emailTitle">邮件标题</param>
        /// <param name="toEmail">接收邮箱</param>
        /// <param name="emailContent"></param>
        /// <returns></returns>
        public async Task SendEmail(string emailTitle, string toEmail, string emailContent, IEnumerable<AttachmentInfo> attachments = null)
        {
            try
            {
                await eMailHelper.SendEMailAsync(
                    emailTitle,
                    emailContent,
                    new MailboxAddress[] { new MailboxAddress(toEmail) },
                    TextFormat.Html, attachments: attachments);
            }
            catch (Exception e)
            {
                Logger.Error("邮件发送失败:" + e.Message + e.StackTrace + e.InnerException);
            }
        }

        /// <summary>
        /// 发送限制管理器
        /// </summary>
        public static class EmailManager
        {
            /// <summary>
            /// 每个邮箱、号码最多每天发送三次
            /// </summary>
            public static int MaxNumPerEmail { get; set; } = 3;

            /// <summary>
            /// 系统每天最多1000
            /// </summary>
            public static int MaxNumPerDay { get; set; } = 1000;

            /// <summary>
            /// 每个IP每天最大次数
            /// </summary>
            public static int MaxNumPerIp { get; set; } = 6;

            /// <summary>
            /// 今天发了多少
            /// </summary>
            public static int TotalSend { get; set; } = 0;

            /// <summary>
            /// 每天的邮件发送情况
            /// </summary>
            public static Dictionary<string, int> EmailSendInfo { get; set; } = new Dictionary<string, int>();

            /// <summary>
            /// 开始时间
            /// </summary>
            public static DateTime StartTime { get; set; } = DateTime.Now;

            /// <summary>
            /// IP地址
            /// </summary>
            public static Dictionary<string, int> IpInfo { get; set; } = new Dictionary<string, int>();
        }

        /// <summary>
        /// 发送邮件,找回密码
        /// 24小时内每个IP只能发送6封，每个邮箱最多3个，每天最多发1000个
        /// </summary>
        /// <param name="emailTitle">邮件标题</param>
        /// <param name="toEmail">接收邮箱</param>
        /// <param name="emailContent"></param>
        /// <returns></returns>
        public async Task SendEmail2(string ipaddr, string emailTitle, string toEmail, string emailContent, IEnumerable<AttachmentInfo> attachments = null)
        {
            try
            {
                TimeSpan ts = DateTime.Now - EmailManager.StartTime;
                if (ts.TotalDays >= 1)
                {
                    EmailManager.StartTime = DateTime.Now;
                    EmailManager.EmailSendInfo = new Dictionary<string, int>();
                }

                if (EmailManager.IpInfo.ContainsKey(ipaddr))
                {
                    var sendedNum = EmailManager.IpInfo[ipaddr];
                    if (sendedNum >= EmailManager.MaxNumPerIp)
                    {
                        throw new OperationException(string.Format(Localizer["YB0214"].Value, sendedNum));
                    }
                    EmailManager.IpInfo[ipaddr] = sendedNum + 1;
                }
                else
                {
                    EmailManager.IpInfo.Add(ipaddr, 1);
                }

                if (EmailManager.EmailSendInfo.ContainsKey(toEmail))
                {
                    var sendedNum = EmailManager.EmailSendInfo[toEmail];
                    if (sendedNum >= EmailManager.MaxNumPerEmail)
                    {
                        throw new OperationException(string.Format(Localizer["YB0215"].Value, sendedNum));
                    }
                    EmailManager.EmailSendInfo[toEmail] = sendedNum + 1;
                }
                else
                {
                    EmailManager.EmailSendInfo.Add(toEmail, 1);
                }

                if (EmailManager.TotalSend >= EmailManager.MaxNumPerDay)
                {
                    throw new OperationException(Localizer["YB0216"].Value);
                }
                EmailManager.TotalSend++;
                StringBuilder sb = new StringBuilder();
                Random random = new Random();
                for (int i = 0; i < 8; i++)
                {
                    sb.Append(random.Next(0, 9));
                }
                var dto = new Domain.DtoModel.Sys.RegisterDto();
                dto.Email = toEmail.ToLower().Trim();
                dto.Password = sb.ToString();
                try
                {
                    var resetResult = await ResetPassWord(dto);

                    if (resetResult.Code == AjaxCode.Success)
                    {
                        await eMailHelper.SendEMailAsync(
                            emailTitle,
                            emailContent = "您的密码:" + dto.Password,
                            new MailboxAddress[] { new MailboxAddress(toEmail) },
                            TextFormat.Html, attachments: attachments);
                    }
                }
                catch
                {
                    throw new OperationException(Localizer["YB0217"].Value);
                }
            }
            catch (Exception e)
            {
                Logger.Info(e.Message + e.StackTrace + e.InnerException);
            }
        }
    }
}